/**
 * 
 */
package org.arga.empresa.repository;

import java.lang.reflect.ParameterizedType;
import java.util.Collection;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 * Default Abstract Implementation of the <code>GenericRepository</code> contract
 * usign JPA constructs.
 * <p>Subclasses must interact with the already given <code>EntityManager</code>
 * object which should have been already injected by the container (protected property).
 * 
 * @author aflores@arga-inc.com
 * @since Dec 22, 2009 11:44:30 PM
 * @param <PK> the Primary Identifier, typically the id.
 * @param <T> the Entity type of this generic repository. 
 */
public abstract class GenericJpaRepository<PK, T> implements GenericRepository<PK, T> {
	/**
	 * Persistent Class type specific to the implementation of this repository. 
	 */
	protected final Class<T> m_persistentClass;
	/**
	 * JPA Entity manager. This bean takes care of performing all CRUD operations 
	 * on behalf of the relational persistent store. 
	 */
	@PersistenceContext protected EntityManager m_entityManager;
	
	/**
	 * Default constructor.
	 */
	@SuppressWarnings("unchecked")
	public GenericJpaRepository() {
		m_persistentClass = (Class<T>) ((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public T createEntity(T entity) {
		if (entity != null) {
			m_entityManager.persist(entity);
			return entity;
		}
		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void deleteEntity(PK id) {
		T entity = findById(id);
		if (entity != null) {
			m_entityManager.remove(entity);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public T findById(PK id) {
		if (id != null) {
			return m_entityManager.find(m_persistentClass, id);
		}
		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("unchecked")
	@Override
	public Collection<T> retrieveAll() {
		Query query = m_entityManager.createQuery("select t from " + m_persistentClass.getName() + " t");
		return (Collection<T>) query.getResultList();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void updateEntity(T entity) {
		if (entity != null) {
			m_entityManager.merge(entity);
		}
	}

}
